﻿
using System.Collections.Generic;
using System.IO;
using System.Windows.Media.Media3D;

namespace LxCFD
{
    public class VTUWriter : XMLWriter, IWriteFile
    {
        public List<ScalarTypes> ExportScalars = new List<ScalarTypes>();
        public bool WriteFile(string filePath)
        {
            using (Writer = new StreamWriter(filePath))
            {
                StartWriter();
                WriteVTUFile();
            }
            return true;
        }

        protected void WriteVTUFile()
        {
            WriteXmlHead("<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">");
            {
                WriteXmlHead("<UnstructuredGrid>");
                foreach (var z in AppRes.FvMesh.Zones)
                {
                    WriteXmlHead(string.Format($"<Piece NumberOfPoints=\"{z.Nodes.Count}\" NumberOfCells=\"{z.Cells.Length}\">"));
                    {
                        WritePoints(z);
                        WriteCells(z);
                        WriteCellData(z);
                    }
                    WriteXmlEnd("</Piece>");
                }
                WriteXmlEnd("</UnstructuredGrid>");
            }
            WriteXmlEnd("</VTKFile>");
        }
        protected void WritePoints(FvZone z)
        {
            WriteXmlHead("<Points>");
            {
                WriteXmlHead("<DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">");
                var nodes = z.Nodes;
                for (int i1 = 0; i1 < nodes.Count; i1++)
                {
                    WriteSpaceEnter(i1, 3);
                    Point3D node = nodes[i1];
                    Writer.Write(string.Format($"{(float)node.X} {(float)node.Y} {(float)node.Z} "));
                }
                Writer.WriteLine();
                WriteXmlEnd("</DataArray>");
            }
            WriteXmlEnd("</Points>");
        }
        protected void WriteCells(FvZone z)
        {
            WriteXmlHead("<Cells>");
            {
                VtuCell[] cells = new VtuCell[z.Cells.Length];
                {
                    int offset = 0;
                    int i1 = 0;
                    for (; i1 <= z.InnerIndex.CellIDs.End; i1++)
                    {
                        if (!cells[i1].AddCellInf_inner(ref z.Cells[i1], z.Faces, ref offset))
                        {
                            LxConsole.Error("输出Cell时出错，无法识别的网格类型");
                        }
                    }
                    for (; i1 < cells.Length; i1++)
                    {
                        if (!cells[i1].AddCellInf_bound(ref z.Cells[i1], z.Faces, ref offset))
                        {
                            LxConsole.Error("输出Cell时出错，无法识别的网格类型");
                        }
                    }
                }
                WriteXmlHead("<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">");
                {
                    for (int i1 = 0; i1 < cells.Length; i1++)
                    {
                        WriteSpaceEnter(i1, 3);
                        foreach (var i in cells[i1].Connect)
                        {
                            Writer.Write(string.Format($"{i} "));
                        }
                    }
                    Writer.WriteLine();
                }
                WriteXmlEnd("</DataArray>");
                WriteXmlHead("<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">");
                {
                    for (int i1 = 0; i1 < cells.Length; i1++)
                    {
                        WriteSpaceEnter(i1, 10);
                        Writer.Write(string.Format($"{cells[i1].OffSet} "));
                    }
                    Writer.WriteLine();
                }
                WriteXmlEnd("</DataArray>");
                WriteXmlHead("<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">");
                {
                    for (int i1 = 0; i1 < cells.Length; i1++)
                    {
                        WriteSpaceEnter(i1, 15);
                        Writer.Write(string.Format($"{cells[i1].Type} "));
                    }
                    Writer.WriteLine();
                }
                WriteXmlEnd("</DataArray>");
            }
            WriteXmlEnd("</Cells>");
        }
        protected void WriteCellData(FvZone z)
        {
            if (ExportScalars.Count == 0 || z.CFDFields == null) return;
            WriteXmlHead("<CellData>");
            {
                foreach (var scalartype in ExportScalars)
                {
                    if (scalartype == ScalarTypes.Velocity)
                    {
                        var uarray = z.CFDFields.GetArray(ScalarTypes.Vel_U);
                        var varray = z.CFDFields.GetArray(ScalarTypes.Vel_V);
                        var warray = z.CFDFields.GetArray(ScalarTypes.Vel_W);
                        if (uarray == null || varray == null || warray == null) continue;
                        WriteXmlHead("<DataArray type=\"Float32\" Name=\"Velocity\" NumberOfComponents=\"3\" format=\"ascii\">");
                        {
                            for (int i1 = 0; i1 < z.Cells.Length; i1++)
                            {
                                WriteSpaceEnter(i1, 3);
                                Writer.Write(string.Format($"{(float)uarray[i1]} {(float)varray[i1]} {(float)warray[i1]} "));
                            }
                            Writer.WriteLine();
                        }
                        WriteXmlEnd("</DataArray>");
                    }
                    else
                    {
                        var array = z.CFDFields.GetArray(scalartype);
                        if (array == null) continue;
                        WriteXmlHead(string.Format($"<DataArray type=\"Float32\" Name=\"{scalartype}\" format=\"ascii\">"));
                        {
                            for (int i1 = 0; i1 < z.Cells.Length; i1++)
                            {
                                WriteSpaceEnter(i1, 5);
                                Writer.Write(string.Format($"{(float)array[i1]} "));
                            }
                            Writer.WriteLine();
                        }
                        WriteXmlEnd("</DataArray>");
                    }
                }
            }
            WriteXmlEnd("</CellData>");
        }

    }
}
